//JQuery Horizontal alignment plugin
(function ($) { $.fn.vAlign = function() { return this.each(function(i){ var h = $(this).height(); var oh = $(this).outerHeight(); var mt = (h + (oh - h)) / 2; $(this).css("margin-top", "-" + mt + "px"); $(this).css("top", "50%"); $(this).css("position", "absolute"); }); }; })(jQuery); (function ($) { $.fn.hAlign = function() { return this.each(function(i){ var w = $(this).width(); var ow = $(this).outerWidth(); var ml = (w + (ow - w)) / 2; $(this).css("margin-left", "-" + ml + "px"); $(this).css("left", "50%"); $(this).css("position", "absolute"); }); }; })(jQuery);

/**
 * Application
 */

ObjectManager = Class.extend({
	init: function()	{
		this.objects = new Array();
		this.context = null;
		this.mainObjects = new Array();
	},

	register: function(obj)	{
		this.objects.push(obj);
	},
	
	registerContext: function(obj)	{
		this.context = obj;
	},
	
	/*
	* main object is one visualize the idea, a main object usually is a collection of main image
	* and other thing support for the display
	*/
	registerMainObjects: function(obj)	{
		this.mainObjects.push(obj);
	},
	
	getMainObjects: function(){
		return this.mainObjects;
	},
	
	remove: function(obj)	{
		/*
		* remove from display
		*/
		var i = this.findIndex(obj.id);
		if (i != -1)	{
			this.objects.splice(i, 1);
		}
		/*
		* remove from mainObjects array
		*/
		for(var j=0;j<this.mainObjects.length;j++)	{
			if(obj.id == this.mainObjects[j].id)		{
				this.mainObjects.splice(j,1);
			}
		}
	},
	
	find: function(objId)	{
		var i = this.findIndex(objId);
		if (i == -1)
			return null;
		return this.objects[i];
	},
	
	findIndex: function(objId)	{
		for(var i=0;i<this.objects.length;i++)	{
			if (objId == this.objects[i].id)	{
				return i;
			}
		}
		return -1;
	}
});

Application = Class.extend({
	init: function()	{
		this.selectedObjects = new Array(); //select multi objects
	},

	begin: function()	{
		if (!this.begun)	{
			this.begun = true;
			this.bindEvents();
			this.setupToolBox();
			this.setupCanvas();
		}
	},
	
	bindEvents: function()	{
		$(document).bind("object_created", this.objectCreated);
		$(document).click(this.clicked);
	},
	
	setupCanvas: function()	{
		var ccd = new ClickCanvasDeselect();
		
		this.main = new Canvas();
		this.main.id = 'main';
		this.main.implement(ccd);
		
		this.pdf = new Canvas();
		this.pdf.id = 'pdf';
		this.pdf.implement(ccd);
	},
	
	setupToolBox: function()	{
		this.objMgr = new ObjectManager();
		this.toolBox = new ToolBox();
		$('body').append(this.toolBox.toHtml());
		this.toolBox.afterCreate();
		this.toolBox.addIconSet("Basic");
		this.toolBox.addIconToSet(0,new Image("images/ballon.png"));
		this.toolBox.addIconToSet(0,new Image("images/stick-man.png"));
		this.toolBox.addIconToSet(0,new Image("images/movie-clapper.png"));
		this.toolBox.addIconToSet(0,new Image("images/cloud.png"));
		this.toolBox.addIconToSet(0,new Image("images/about-frame.png"));
		this.toolBox.addIconToSet(0,new Image("images/email.png"));
		this.toolBox.addIconToSet(0,new Image("images/square.png"));
		this.toolBox.addIconSet("Biz");
		this.toolBox.addIconToSet(1,new Image("images/dollar-sign.png"));
		this.toolBox.addIconToSet(1,new Image("images/contacte.png"));		
		this.toolBox.addIconToSet(1,new Image("images/laptop.png"));
		this.toolBox.addIconToSet(1,new Image("images/conference.png"));		
		var button = new Button("Export as JPG");
		var btnSave = new Button("Save");
		var btnLoad = new Button("Load");
		this.toolBox.addObject(button);
		this.toolBox.addObject(btnSave);
		this.toolBox.addObject(btnLoad);
		button.implement(new ClickExportJPG());	
		btnSave.implement(new SaveDiagram());
		btnLoad.implement(new LoadDiagram());
	},
	
	getMainArea: function()	{
		return this.main;
	},
	
	getToolBox: function()	{
		return this.toolBox;
	},
	
	getObjectManager: function()	{
		return this.objMgr;
	},
	
	objectCreated: function()	{
		
	},
	
	clicked: function()	{
	},
	
	select: function(obj)	{
		if (this.selected != null)	{
			this.selected.deselect();
		}
		if (obj != null)	{
			obj.select();
		}
		this.selected = obj;
		context = this.objMgr.context;
		if (context != null){
			context.dispose();
		}	
	},
	
	deselect: function()	{
		this.select(null);
	}
});

/**
 * Base displayable object
 */
DisplayObject = Class.extend	({
	init: function()	{
		this.id=0;
		this.type = "default";
		this.htmlClasses = new Array();
		this.interfaces = new Array();
		var objMgr = app.getObjectManager();
		this.className = "DisplayObject";
		objMgr.register(this);
	},
	
	deserializeStyle: function(style)	{
		this.deserializedStyle = style;
	},
	
	serializeStyle: function()	{
		return this.getAttribute('style');
	},
	
	serialize: function()	{
		var obj = {};
		obj.className = this.className;
		return obj;
	},
	
	getPosition: function()	{
		return this.access().offset();
	},
	
	moveTo: function(top, left)	{
		this.access().css('left', left+"px");
		this.access().css('top', top+"px");
	},
	
	center: function()	{
		this.access().hAlign();
		this.access().vAlign();
	},
	
	moveToBR: function(bottom, right)	{
		this.access().css('bottom', bottom+"px");
		this.access().css('right', right+"px");
	},

	getType: function()	{
		return "ij-"+this.type;
	},

	toHtml: function()	{
		return "";
	},
	
	getParent: function()	{
		return this.parent;
	},
	
	setParent: function(parent)	{
		this.parent = parent;
	},
	
	getId: function()	{
		return this.id;
	},
	
	access: function()	{
		return $('#'+this.id);
	},
	
	resizeTo: function(width, height)	{
		this.access().css('width', width+"px");
		this.access().css('height', height+"px");
	},
	
	getDimension: function()	{
		var dim = {};
		dim.width = this.access().width();
		dim.height = this.access().height();
		return dim;
	},
	
	setStyle: function(styleName, value)	{
		this.access().css(styleName, value);
	},
	
	setAttribute: function(attrName, value)	{
		this.access().attr(attrName, value);
	},
	
	getAttribute: function(attrName)	{
		return this.access().attr(attrName);
	},
	
	implement: function(implementor)	{
		this.interfaces.push(implementor);
		this.updateInterfaces();
	},
	
	addClass: function(className)	{
		this.htmlClasses.push(className);
		this.updateClasses();
	},
	
	getHtmlClasses: function()	{
		return this.htmlClasses;
	},
	
	show: function()	{
		this.access().show();
	},
	
	hide: function()	{
		this.access().hide();
	},
	
	dispose: function()	{
		this.access().remove();
		app.getObjectManager().remove(this);
	},
	
	updateClasses: function()	{
		var classes = this.getHtmlClasses();
		var classNames = this.getType();
		for(var i=0;i<classes.length;i++)	{
			classNames+= " "+classes[i];
		}
		this.access().attr('class', classNames);
	},
	
	updateInterfaces: function()	{
		var interfaces = this.interfaces;
		for(var i=0;i<interfaces.length;i++)	{
			var implementor = interfaces[i];
			if (implementor != null)	{
				implementor.implement(this);
			}
		}
	},
	
	afterLoad: function()	{
		this.setAttribute('style', this.deserializedStyle);
	},
	
	/**
	 * Update HTML element when properties are changed
	 */
	update: function()	{
		this.updateClasses();
		this.updateInterfaces();
	},
	
	afterCreate: function()	{
		this.update();
		new EventBinder().fireEvent(this.access(), 'object_created');
	}
});

/**
 * Container class. A container is an object which 'contains' other objects
 */
Container = DisplayObject.extend({
	init: function()	{
		this._super();
		this.objects = new Array();
		this.type = "container";
		this.className = "Container";
	},
	
	addObject: function(obj)	{
		this.objects.push(obj);
		this.access().append(obj.toHtml());
		obj.setParent(this);
		obj.afterCreate();
	},
	
	afterCreate: function(obj)	{
		this._super();
		for(var i=0;i<this.objects.length;i++)	{
			this.objects[i].afterCreate();
		}
	},
	
	removeObject: function(object)	{
		for(var i=0;i<this.objects.length;i++)	{
			var obj = this.objects[i];
			if (obj.getId() == object.getId())	{
				this.objects.splice(i, 1);
				object.dispose();;
			}
		}
	},
	
	getObjects: function()	{
		return this.objects;
	},
	
	toHtml: function()	{
		var html = "";
		for(var i=0;i<this.objects.length;i++)	{
			html += this.objects[i].toHtml();
		}
		return html;
	}
});

Canvas = Container.extend({
	init: function()	{
		this._super();
		// FIXME: Store this list in another location?
		this.type = "canvas";
		this.id = generateId('canvas');
		this.className = "Canvas";
	},

	toHtml: function()	{
		return "<div id='"+this.id+"'>"+this._super()+"</div>";
	}
});

/*
 * Font
 */
Font = Class.extend({
	init:function()	{
		this.fontFamily = 'Tahoma,sans-serif';
		this.fontSize = "12px";
		this.bold = false;
		this.italic = false;
		this.color = "#000000";
	},
	
	setFont: function(fontFamily, fontSize, bold, italic, color)	{
		this.fontFamily = fontFamily;
		this.fontSize = fontSize;
		this.bold = bold;
		this.italic = italic;
		this.color = color;
	},
	
	setFontFamily: function(fontFamily)	{
		this.fontFamily = fontFamily;
	},
	
	getFontFamily: function()	{
		return this.fontFamily;
	},
	
	setFontSize: function(fontSize)	{
		this.fontSize = fontSize;
	},
	
	getFontSize: function()	{
		return this.fontSize;
	},
	
	setBold: function(bold)	{
		this.bold = bold;
	},
	
	getBold: function()	{
		return this.bold;
	},
	
	setItalic: function(italic)	{
		this.italic = italic;
	},
	
	getItalic: function()	{
		return this.italic;
	},
	
	setColor: function(color)	{
		this.color = color;
	},
	
	getColor: function()	{
		return this.color;
	}
});


/**
 * IMPLEMENTOR & HANDLERS
 */
InterfaceImplementor = Class.extend({
	init: function(){
	},

	implement: function(obj)	{
		
	},

	bind: function(obj, handler)	{
		new EventBinder().bindEvent(obj, handler);
	}
});

Handler = Class.extend({
	init: function(){
	},
	
	getEventName: function()	{
		return "";
	},
	
	onEvent: function(e)	{
		
	}
});
